package com.atguigu.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.client.CartFeignClient;
import com.atguigu.client.ProductFeignClient;
import com.atguigu.constant.MqConst;
import com.atguigu.entity.OrderDetail;
import com.atguigu.entity.OrderInfo;
import com.atguigu.enums.ProcessStatus;
import com.atguigu.mapper.OrderInfoMapper;
import com.atguigu.service.OrderDetailService;
import com.atguigu.service.OrderInfoService;
import com.atguigu.util.HttpClientUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 订单表 订单表 服务实现类
 * </p>
 *
 * @author zhangqiang
 * @since 2022-01-15
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private CartFeignClient cartFeignClient;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Value("${cancel.order.delay}")
    private Integer cancelOrderDelay;
//    @Autowired
//    private ThreadPoolExecutor threadPoolExecutor;

    @Transactional
    @Override
    public Long saveOrderAndDetail(OrderInfo orderInfo) {
        //商品对外交易号 给微信或者支付宝
        String outTradeNo="atguigu"+System.currentTimeMillis()+new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //订单主体信息
        orderInfo.setTradeBody("天气有点热 需要爽一把");
        orderInfo.setCreateTime(new Date());
        //订单支付过期时间 默认设置30分钟 一天
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.MINUTE,30);
        orderInfo.setExpireTime(instance.getTime());
        //订单进度状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        //a.保存订单基本信息
        baseMapper.insert(orderInfo);
        //b.保存订单详情信息
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            orderDetail.setOrderId(orderInfo.getId());
        }
        orderDetailService.saveBatch(orderDetailList);
        //发送一个延迟消息 超时取消订单
        rabbitTemplate.convertAndSend(
                MqConst.CANCEL_ORDER_EXCHANGE,
                MqConst.CANCEL_ORDER_ROUTE_KEY,
                orderInfo.getId(),
                correlationData ->{
                    correlationData.getMessageProperties().setDelay(cancelOrderDelay);
                    return correlationData;
                }
        );
        return orderInfo.getId();

    }

    @Override
    public String generateTradeNo(String userId) {
        String tradeNo= UUID.randomUUID().toString();
        //把流水号放入redis当中
        String tradeNoKey="user:"+userId+":tradeNo";
        redisTemplate.opsForValue().set(tradeNoKey,tradeNo);
        return tradeNo;
    }

    @Override
    public boolean checkTradeNo(String tradeNoUI, String userId) {
        //把流水号放入redis当中
        String tradeNoKey="user:"+userId+":tradeNo";
        String redisTradeNo =(String) redisTemplate.opsForValue().get(tradeNoKey);
        return tradeNoUI.equals(redisTradeNo);
    }

    @Override
    public void deleteTradeNo(String userId) {
        String tradeNoKey="user:"+userId+":tradeNo";
       redisTemplate.delete(tradeNoKey);
    }

    @Override
    public List<String> checkStockAndPrice(String userId, OrderInfo orderInfo) {
        //用于提示用户商品库存信息
        List<String> warningInfoList = new ArrayList<>();
        //拿到送货清单
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        if(!CollectionUtils.isEmpty(orderDetailList)){
            for (OrderDetail orderDetail : orderDetailList) {
                Long skuId = orderDetail.getSkuId();
                String skuNum = orderDetail.getSkuNum();
                //判断库存是否足够get http://localhost:8100/hasStock?skuId=10221&num=2
                String result = HttpClientUtil.doGet("http://localhost:8100/hasStock?skuId=" + skuId + "&num=" + skuNum);
                //0：无库存   1：有库存
                if("0".equals(result)){
                    warningInfoList.add(orderDetail.getSkuName()+"库存不足");
                }
                //验证价格是否为最新价格
                BigDecimal realTimePrice = productFeignClient.getSkuPrice(skuId);
                if(orderDetail.getOrderPrice().compareTo(realTimePrice)!=0){
                    warningInfoList.add(orderDetail.getSkuName()+"价格有变化,需要刷新页面");
                    //更新缓存信息
                    cartFeignClient.queryFromDbToRedis(userId);
                }
            }
        }
        return warningInfoList;
    }

//    @Override
//    public List<String> checkStockAndPrice(String userId, OrderInfo orderInfo) {
//        //用于提示用户商品库存信息
//        List<String> warningInfoList = new ArrayList<>();
//        List<CompletableFuture> multiFutureList = new ArrayList<>();
//        //拿到送货清单
//        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
//        if(!CollectionUtils.isEmpty(orderDetailList)){
//            for (OrderDetail orderDetail : orderDetailList) {
//                Long skuId = orderDetail.getSkuId();
//                String skuNum = orderDetail.getSkuNum();
//
//                CompletableFuture<Void> checkStockFuture = CompletableFuture.runAsync(() -> {
//                    //判断库存是否足够get http://localhost:8100/hasStock?skuId=10221&num=2
//                    String result = HttpClientUtil.doGet("http://localhost:8100/hasStock?skuId=" + skuId + "&num=" + skuNum);
//                    //0：无库存   1：有库存
//                    if ("0".equals(result)) {
//                        warningInfoList.add(orderDetail.getSkuName() + "库存不足");
//                    }
//                },threadPoolExecutor);
//                multiFutureList.add(checkStockFuture);
//
//                CompletableFuture<Void> checkPriceFuture = CompletableFuture.runAsync(() -> {
//                    //验证价格是否为最新价格
//                    BigDecimal realTimePrice = productFeignClient.getSkuPrice(skuId);
//                    if(orderDetail.getOrderPrice().compareTo(realTimePrice)!=0){
//                        warningInfoList.add(orderDetail.getSkuName()+"价格有变化,需要刷新页面");
//                        //更新缓存信息
//                        cartFeignClient.queryFromDbToRedis(userId);
//                    }
//                },threadPoolExecutor);
//                multiFutureList.add(checkPriceFuture);
//            }
//        }
//        //需要两个异步都执行完成才能返回
//        CompletableFuture[] completableFuture= new CompletableFuture[multiFutureList.size()];
//        CompletableFuture.allOf(multiFutureList.toArray(completableFuture)).join();
//        return warningInfoList;
//    }

    @Override
    public void updateOrderStatus(OrderInfo orderInfo, ProcessStatus processStatus) {
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        baseMapper.updateById(orderInfo);
    }

    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        //1.查询订单基本信息
        OrderInfo orderInfo = baseMapper.selectById(orderId);
        //2.查询订单详情信息
        if(orderInfo!=null){
            QueryWrapper<OrderDetail> wrapper = new QueryWrapper<>();
            wrapper.eq("order_id",orderId);
            List<OrderDetail> orderDetailList = orderDetailService.list(wrapper);
            orderInfo.setOrderDetailList(orderDetailList);
        }
        return orderInfo;
    }

    @Override
    public void sendMsgToWareHouse(OrderInfo orderInfo) {
        //a.将订单状态改为已通知仓库
        updateOrderStatus(orderInfo,ProcessStatus.NOTIFIED_WARE);
        //b.需要组织一个json类型的数据给仓库系统
        Map<String, Object> jsonDataMap=assembleWareHouseData(orderInfo);
        String jsonData=JSON.toJSONString(jsonDataMap);
        //c.发消息给仓库系统
        rabbitTemplate.convertAndSend(MqConst.DECREASE_STOCK_EXCHANGE,MqConst.DECREASE_STOCK_ROUTE_KEY,jsonData);
    }



    private Map<String, Object> assembleWareHouseData(OrderInfo orderInfo) {
        //构建一个map结构用于封装数据
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("orderId",orderInfo.getId());
        dataMap.put("consignee",orderInfo.getConsignee());
        dataMap.put("consigneeTel",orderInfo.getConsigneeTel());
        dataMap.put("orderComment",orderInfo.getOrderComment());
        dataMap.put("orderBody",orderInfo.getTradeBody());
        dataMap.put("deliveryAddress",orderInfo.getDeliveryAddress());
        dataMap.put("paymentWay",2);
        //TODO 这里还有一个非常重要的字段
        dataMap.put("wareId","1");
        //商品清单
        List<Map> orderDetailMapList = new ArrayList<>();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            Map<String, Object> orderDetailMap = new HashMap<>();
            orderDetailMap.put("skuId",orderDetail.getSkuId());
            orderDetailMap.put("skuNum",orderDetail.getSkuNum());
            orderDetailMap.put("skuName",orderDetail.getSkuName());
            orderDetailMapList.add(orderDetailMap);
        }
        dataMap.put("details",orderDetailMapList);
        return dataMap;
    }

    @Override
    public String splitOrder(Long orderId, String wareHouseIdSkuIdMapJson) {
        //1.获取到原始订单
        OrderInfo parentOrderInfo = getOrderInfo(orderId);
        //把接收到的参数转换为list[{"wareHouseId":"1","skuIdList":["24,30,31"]},{"wareHouseId":"2","skuIdList":["25,26"]}]
        List<Map> wareHouseIdSkuIdMapList = JSON.parseArray(wareHouseIdSkuIdMapJson, Map.class);
        //用于存储返回给库存系统的信息集合
        List<Map<String, Object>> assembleWareHouseDataList = new ArrayList<>();
        for (Map wareHouseIdSkuIdMap : wareHouseIdSkuIdMapList) {
            String wareHouseId = (String)wareHouseIdSkuIdMap.get("wareHouseId");
            List<String> childSkuIdList =(List<String>) wareHouseIdSkuIdMap.get("skuIdList");
            //2.设置子订单信息
            OrderInfo childOrder = new OrderInfo();
            //累到不行
            //childOrder.setConsignee(parentOrderInfo.getConsignee());
            BeanUtils.copyProperties(parentOrderInfo,childOrder);
            childOrder.setParentOrderId(orderId);
            childOrder.setId(null);
            //设置仓库id
            childOrder.setWareHouseId(wareHouseId);
            //3.设置子订单详情信息
            ArrayList<OrderDetail> childOrderDetailList = new ArrayList<>();
            BigDecimal childTotalMoney=new BigDecimal(0);
            List<OrderDetail> parentOrderDetailList = parentOrderInfo.getOrderDetailList();
            for (OrderDetail parentOrderDetail : parentOrderDetailList) {
                for (String childSkuId : childSkuIdList) {
                    if(parentOrderDetail.getSkuId()==Long.parseLong(childSkuId)){
                        BigDecimal orderPrice = parentOrderDetail.getOrderPrice();
                        String skuNum = parentOrderDetail.getSkuNum();
                        childTotalMoney.add(orderPrice.multiply(new BigDecimal(skuNum)));
                        childOrderDetailList.add(parentOrderDetail);
                    }
                }
            }
            childOrder.setOrderDetailList(childOrderDetailList);
            childOrder.setTotalMoney(childTotalMoney);
            //4.保存子订单及详情信息
            saveOrderAndDetail(childOrder);
            Map<String, Object> jsonDataMap = assembleWareHouseData(childOrder);
            assembleWareHouseDataList.add(jsonDataMap);

        }
        //5.原始订单有原来的状态改为split
        updateOrderStatus(parentOrderInfo,ProcessStatus.SPLIT);
        //6.把订单相关信息返回给库存系统
        return JSON.toJSONString(assembleWareHouseDataList);
    }
}
